package com.search;

import java.io.File;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;

import com.common.FIELDS;

/**
 * Clase encargada de realizar las búsquedas sobre el índice.
 * 
 * @author agu
 * 
 */
public class Searcher {

	/**
	 * Lugar donde está almacenado el índice.
	 */
	static final File INDEX_DIR = new File("resources/index");

	public Searcher() {}

	/**
	 * este método es el encargado de invocar al método getdocs con cada uno de
	 * los distintos campos (fields) de búsqueda y el input de entrada. Le da un
	 * formato a los resultados y los retorna.
	 * 
	 * @param input
	 *            el input que se utilizará para la búsqueda
	 * @throws IOException
	 * @throws CorruptIndexException
	 * @throws ParseException
	 */
	public int search(String input, int pageSize) throws CorruptIndexException,
			IOException, ParseException {

		IndexSearcher indexSearcher = new IndexSearcher(FSDirectory
				.open(INDEX_DIR));

		Set<ScoreDoc> documents = new HashSet<ScoreDoc>();

		// for each field get all documents regarding this search
		for (FIELDS field : FIELDS.values())
			documents.addAll(getdocs(input, field.toString(), indexSearcher,
					pageSize));

		for (String doc : DocumentFormatter.formatDocuments(documents,
				indexSearcher))
			System.out.println(doc);

		return documents.size();
	}

	/**
	 * dado un input y un field en el cual buscar, este método creará un query a
	 * partir del queryparser, y buscará los documentos con ese query.
	 * 
	 * @param input
	 *            las palabras ingresadas por el usuario para la búsqueda
	 * @param field
	 *            el campo sobre el cuál se quiere buscar
	 * @param indexSearcher
	 *            el índice.
	 * @return un set con los documentos encontrados.
	 * @throws CorruptIndexException
	 * @throws IOException
	 * @throws ParseException
	 */
	private Set<ScoreDoc> getdocs(String input, String field,
			IndexSearcher indexSearcher, int pageSize)
			throws CorruptIndexException, IOException, ParseException {

		QueryParser queryParser = new QueryParser(Version.LUCENE_30, field,
				new StandardAnalyzer(Version.LUCENE_30));

		// crea el query utilizando el query parser.
		Query query = queryParser.parse(input);

		// realiza la busqueda
		TopDocs topDocs = indexSearcher.search(query, pageSize);

		Set<ScoreDoc> documents = new HashSet<ScoreDoc>();

		// por cada resultado
		for (ScoreDoc scoreDoc : topDocs.scoreDocs)
			documents.add(scoreDoc);

		return documents;
	}
}